/*
 * Copyright (c) 2020 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.diegocarloslima.fgelv.sample.slice;

import com.diegocarloslima.fgelv.lib.ExpandableListAdapter;
import com.diegocarloslima.fgelv.lib.FloatingGroupExpandableListView;
import com.diegocarloslima.fgelv.lib.util.ResUtil;

import com.diegocarloslima.fgelv.sample.ResourceTable;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.aafwk.content.Operation;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.*;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.utils.Color;
import ohos.agp.utils.TextAlignment;
import ohos.agp.window.dialog.ToastDialog;
import ohos.media.image.PixelMap;
import ohos.utils.net.Uri;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Optional;

public class ExpandableListAbilitySlice extends AbilitySlice {
    private FloatingGroupExpandableListView mGroupContainer;
    private ArrayList<String> mFinalGroupNameItem = new ArrayList<>(), mGroupNameItem = new ArrayList<>(), mTempGroupNameItem = new ArrayList<>(), mTempChildNameItem = new ArrayList<>();
    private ArrayList<Integer> mGroupImageItem = new ArrayList<>();

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        ComponentContainer rootView = (ComponentContainer) LayoutScatter.getInstance(this).parse(ResourceTable.Layout_sample_ability_list, null, false);
        super.setUIContent(rootView);
        initViews(rootView);
    }

    /**
     * This method is used to init view components
     *
     * @param rootView parent view
     */
    private void initViews(ComponentContainer rootView) {
        getGroupItems();
        getGroupIcons();
        prepareHeaderFooterView(rootView);
        ScrollView parentLayout = (ScrollView) rootView.findComponentById(ResourceTable.Id_root);
        parentLayout.setBackground(getShapeElement(ResUtil.getColor(this, ResourceTable.Color_back_gray)));
        DirectionalLayout dividerLayout = (DirectionalLayout) rootView.findComponentById(ResourceTable.Id_divider);
        dividerLayout.setBackground(getShapeElement(Color.BLACK.getValue()));
        mGroupContainer = (FloatingGroupExpandableListView) rootView.findComponentById(ResourceTable.Id_lcGroupItems);
        prepareExpandableListAdapter();
    }

    /**
     * This method is used to prepare header & footer view
     *
     * @param rootView parent view
     */
    private void prepareHeaderFooterView(ComponentContainer rootView) {
        // Header image
        Image headerImage = (Image) rootView.findComponentById(ResourceTable.Id_ivHeaderIcon);
        setHeaderFooterImage(headerImage, ResourceTable.Media_header);
        // Footer image
        Image footerImage = (Image) rootView.findComponentById(ResourceTable.Id_ivFooterIcon);
        setHeaderFooterImage(footerImage, ResourceTable.Media_github);
        // Footer container
        DirectionalLayout footerLayout = (DirectionalLayout) rootView.findComponentById(ResourceTable.Id_footerContainer);
        footerLayout.setBackground(getShapeElement(ResUtil.getColor(this, ResourceTable.Color_text_white)));
        footerLayout.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                openIntentWithURI();
            }
        });
    }

    /**
     * This method is used to launch URI on browser
     */
    private void openIntentWithURI() {
        Operation operationBuilder = new Intent.OperationBuilder()
                .withUri(Uri.parse(ResUtil.getString(this, ResourceTable.String_github_link)))
                .build();
        Intent intent = new Intent();
        intent.setOperation(operationBuilder);
        startAbility(intent);
    }

    /**
     * This method is used to set header & footer view images
     *
     * @param image      Image component to set image
     * @param imageResId Image resource id
     */
    private void setHeaderFooterImage(Image image, int imageResId) {
        Optional<PixelMap> groupIconPixelMap = ResUtil.getPixelMap(this, imageResId);
        groupIconPixelMap.ifPresent(image::setPixelMap);
        image.setScaleMode(Image.ScaleMode.STRETCH);
    }

    /**
     * This method is used to prepare group items
     */
    private void getGroupItems() {
        mGroupNameItem.add(ResUtil.getString(this, ResourceTable.String_item_cupcake));
        mGroupNameItem.add(ResUtil.getString(this, ResourceTable.String_item_donut));
        mGroupNameItem.add(ResUtil.getString(this, ResourceTable.String_item_eclair));
        mGroupNameItem.add(ResUtil.getString(this, ResourceTable.String_item_froyo));
        mGroupNameItem.add(ResUtil.getString(this, ResourceTable.String_item_gingerbread));
        mGroupNameItem.add(ResUtil.getString(this, ResourceTable.String_item_honeycomb));
        mGroupNameItem.add(ResUtil.getString(this, ResourceTable.String_item_ice_cream_sandwich));
        mGroupNameItem.add(ResUtil.getString(this, ResourceTable.String_item_jelly_bean));
        mGroupNameItem.add(ResUtil.getString(this, ResourceTable.String_item_kitkat));
        mFinalGroupNameItem.addAll(mGroupNameItem);
    }

    /**
     * This method is used to prepare group items images
     */
    private void getGroupIcons() {
        mGroupImageItem.add(ResourceTable.Media_cupcake);
        mGroupImageItem.add(ResourceTable.Media_donut);
        mGroupImageItem.add(ResourceTable.Media_eclair);
        mGroupImageItem.add(ResourceTable.Media_froyo);
        mGroupImageItem.add(ResourceTable.Media_gingerbread);
        mGroupImageItem.add(ResourceTable.Media_honeycomb);
        mGroupImageItem.add(ResourceTable.Media_ice_cream_sandwich);
        mGroupImageItem.add(ResourceTable.Media_jelly_bean);
        mGroupImageItem.add(ResourceTable.Media_kitkat);
    }

    /**
     * This method is used to prepare adapter for list data
     */
    private void prepareExpandableListAdapter() {
        ExpandableListAdapter expandableListAdapter = new ExpandableListAdapter<String>(this, ResourceTable.Layout_sample_ability_list_group_item, mGroupNameItem, mGroupImageItem) {
            @Override
            protected void bind(ViewHolder holder, String text, Integer image, int position) {
                if (!mTempChildNameItem.contains(text)) {
                    // Set green background
                    holder.setGroupItemBackground(ResourceTable.Id_groupContainer, ResourceTable.Color_back_green);
                    holder.setText(ResourceTable.Id_tvGroupTitle, text, Color.WHITE, ResUtil.getIntDimen(ExpandableListAbilitySlice.this, ResourceTable.Float_text_20fp));
                    holder.setGroupImage(ResourceTable.Id_ivGroupIcon, image, ShapeElement.RECTANGLE, Image.ScaleMode.STRETCH, ResourceTable.Color_back_green);
                    if (!mTempGroupNameItem.contains(text)) {
                        // Set divider & plus icon
                        holder.setGroupItemDivider(ResourceTable.Id_childDivider, Color.BLACK.getValue());
                        holder.setGroupImage(ResourceTable.Id_ivPlusMinusIcon, ResourceTable.Media_plus, ShapeElement.OVAL, Image.ScaleMode.CENTER, ResourceTable.Color_back_green);
                    } else {
                        // Remove divider & minus icon
                        holder.setGroupItemDivider(ResourceTable.Id_childDivider, Color.TRANSPARENT.getValue());
                        holder.setGroupImage(ResourceTable.Id_ivPlusMinusIcon, ResourceTable.Media_minus, ShapeElement.OVAL, Image.ScaleMode.CENTER, ResourceTable.Color_back_green);
                    }
                } else {
                    // Add child items to list
                    holder.setText(ResourceTable.Id_tvGroupTitle, text, Color.BLACK, ResUtil.getIntDimen(ExpandableListAbilitySlice.this, ResourceTable.Float_text_15fp));
                    holder.setChildImage(ResourceTable.Id_ivGroupIcon, image, ResourceTable.Float_width_50vp, ResourceTable.Float_width_50vp, ResourceTable.Float_margin_60vp);
                    holder.setGroupItemDivider(ResourceTable.Id_childDivider, Color.TRANSPARENT.getValue());
                }
            }
        };
        mGroupContainer.setAdapter(expandableListAdapter);

        expandableListAdapter.setOnItemClickListener(new ExpandableListAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(Component component, int position) {
                String clickedItem = mGroupNameItem.get(position);
                if (!mTempChildNameItem.contains(clickedItem)) {
                    if (mTempGroupNameItem.contains(clickedItem)) {
                        int actualItemPosition = mFinalGroupNameItem.indexOf(clickedItem);
                        removeChildItems(actualItemPosition, clickedItem);
                        mTempGroupNameItem.remove(clickedItem);
                    } else {
                        int actualItemPosition = mFinalGroupNameItem.indexOf(clickedItem);
                        addChildItems(actualItemPosition, clickedItem);
                        mTempGroupNameItem.add(clickedItem);
                    }
                    expandableListAdapter.setData(mGroupNameItem);
                } else {
                    showToast();
                }
            }
        });
    }

    /**
     * This method is used to add child items in list
     *
     * @param actualPosition position of group item
     * @param clickedItem    name of clicked item
     */
    private void addChildItems(int actualPosition, String clickedItem) {
        String[] childItems = childItems().get(actualPosition);
        int itemPositionFromGroup = mGroupNameItem.indexOf(clickedItem);
        for (String item : childItems) {
            itemPositionFromGroup = itemPositionFromGroup + 1;
            mGroupNameItem.add(itemPositionFromGroup, item);
            mTempChildNameItem.add(item);
            mGroupImageItem.add(itemPositionFromGroup, ResourceTable.Media_child_indicator);
        }
    }

    /**
     * This method is used to remove child item
     *
     * @param position    position of group item
     * @param clickedItem name of the clicked item
     */
    private void removeChildItems(int position, String clickedItem) {
        String[] items = childItems().get(position);
        int itemPositionFromGroup = mGroupNameItem.indexOf(clickedItem);
        for (String name : items) {
            mGroupNameItem.remove(itemPositionFromGroup + 1);
            mGroupImageItem.remove(itemPositionFromGroup + 1);
            mTempChildNameItem.remove(name);
        }
    }

    /**
     * This method is used to prepare map based on group item index
     *
     * @return HashMap
     */
    private HashMap<Integer, String[]> childItems() {
        HashMap<Integer, String[]> map = new HashMap<>();
        map.put(0, new String[]{ResUtil.getString(this, ResourceTable.String_item_child_cupcake)});
        map.put(1, new String[]{ResUtil.getString(this, ResourceTable.String_item_child_donut)});
        map.put(2, new String[]{
                ResUtil.getString(this, ResourceTable.String_item_child_eclair1),
                ResUtil.getString(this, ResourceTable.String_item_child_eclair2),
                ResUtil.getString(this, ResourceTable.String_item_child_eclair3)});
        map.put(3, new String[]{
                ResUtil.getString(this, ResourceTable.String_item_child_froyo1),
                ResUtil.getString(this, ResourceTable.String_item_child_froyo2),
                ResUtil.getString(this, ResourceTable.String_item_child_froyo3),
                ResUtil.getString(this, ResourceTable.String_item_child_froyo4)});
        map.put(4, new String[]{
                ResUtil.getString(this, ResourceTable.String_item_child_gingerbread1),
                ResUtil.getString(this, ResourceTable.String_item_child_gingerbread2),
                ResUtil.getString(this, ResourceTable.String_item_child_gingerbread3),
                ResUtil.getString(this, ResourceTable.String_item_child_gingerbread4),
                ResUtil.getString(this, ResourceTable.String_item_child_gingerbread5),
                ResUtil.getString(this, ResourceTable.String_item_child_gingerbread6),
                ResUtil.getString(this, ResourceTable.String_item_child_gingerbread7),
                ResUtil.getString(this, ResourceTable.String_item_child_gingerbread8)});
        map.put(5, new String[]{
                ResUtil.getString(this, ResourceTable.String_item_child_honeycomb1),
                ResUtil.getString(this, ResourceTable.String_item_child_honeycomb2),
                ResUtil.getString(this, ResourceTable.String_item_child_honeycomb3),
                ResUtil.getString(this, ResourceTable.String_item_child_honeycomb4),
                ResUtil.getString(this, ResourceTable.String_item_child_honeycomb5),
                ResUtil.getString(this, ResourceTable.String_item_child_honeycomb6),
                ResUtil.getString(this, ResourceTable.String_item_child_honeycomb7),
                ResUtil.getString(this, ResourceTable.String_item_child_honeycomb8),
                ResUtil.getString(this, ResourceTable.String_item_child_honeycomb9)});
        map.put(6, new String[]{
                ResUtil.getString(this, ResourceTable.String_item_child_ice_cream_sandwich1),
                ResUtil.getString(this, ResourceTable.String_item_child_ice_cream_sandwich2),
                ResUtil.getString(this, ResourceTable.String_item_child_ice_cream_sandwich3),
                ResUtil.getString(this, ResourceTable.String_item_child_ice_cream_sandwich4),
                ResUtil.getString(this, ResourceTable.String_item_child_ice_cream_sandwich5)});
        map.put(7, new String[]{
                ResUtil.getString(this, ResourceTable.String_item_child_jelly_bean1),
                ResUtil.getString(this, ResourceTable.String_item_child_jelly_bean2),
                ResUtil.getString(this, ResourceTable.String_item_child_jelly_bean3),
                ResUtil.getString(this, ResourceTable.String_item_child_jelly_bean4),
                ResUtil.getString(this, ResourceTable.String_item_child_jelly_bean5),
                ResUtil.getString(this, ResourceTable.String_item_child_jelly_bean6),
                ResUtil.getString(this, ResourceTable.String_item_child_jelly_bean7),
                ResUtil.getString(this, ResourceTable.String_item_child_jelly_bean8)
        });
        map.put(8, new String[]{ResUtil.getString(this, ResourceTable.String_item_child_kitkat)});
        return map;
    }

    /**
     * This method is used to show toast dialog based on the given message
     */
    private void showToast() {
        ToastDialog toastDialog = new ToastDialog(this);
        toastDialog.setAlignment(TextAlignment.BOTTOM);
        toastDialog.setText(ResUtil.getString(this, ResourceTable.String_clicked_on_child_item));
        toastDialog.show();
    }

    /**
     * This method is used to prepare the background shape element based on color
     *
     * @param color color for the shape element
     * @return ShapeElement
     */
    private ShapeElement getShapeElement(int color) {
        ShapeElement shapeElement = new ShapeElement();
        shapeElement.setShape(ShapeElement.RECTANGLE);
        shapeElement.setRgbColor(RgbColor.fromArgbInt(color));
        return shapeElement;
    }
}